package com.qire.manhua.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.os.Build;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.widget.LinearLayout;

import com.qire.common.basic.ObjectUtil;
import com.qire.manhua.R;
import com.qire.manhua.view.linkageBehaviors.CoordinatorWrapper;
import com.qire.manhua.view.linkageBehaviors.CoordinatorWrapper.CoordinatorHeaderListener;
import com.qire.manhua.view.linkageBehaviors.CoordinatorWrapper.CoordinatorLayoutListener;
import com.qire.manhua.view.linkageBehaviors.ViewOffsetBehavior;

import java.util.ArrayList;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.coordinatorlayout.widget.CoordinatorLayout;
//import androidx.coordinatorlayout.widget.CoordinatorLayout.DefaultBehavior;
import androidx.core.view.WindowInsetsCompat;

/**
 * 协调BarLayout
 */
//@DefaultBehavior(SummerHeaderBehavior.class)
public class CoordinatorBarLayout extends LinearLayout {

    private WindowInsetsCompat lastInsets;

    private ArrayList<CoordinatorHeaderListener> headerListeners;
    private ArrayList<CoordinatorLayoutListener> layoutListeners;

    public CoordinatorBarLayout(Context context) {
        this(context, null);
    }

    public CoordinatorBarLayout(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CoordinatorBarLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        this(context, attrs, defStyleAttr, 0);
    }

    public CoordinatorBarLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    @Override
    public void setOrientation(int orientation) {
        if (orientation != VERTICAL) {
            throw new IllegalArgumentException("CoordinatorBarLayout is always vertical and does not support horizontal orientation");
        } else {
            super.setOrientation(orientation);
        }
    }

    @Override
    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
        return p instanceof LayoutParams;
    }

    @Override
    protected LayoutParams generateDefaultLayoutParams() {
        return new LayoutParams(-1, -2);
    }

    @Override
    public LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new LayoutParams(this.getContext(), attrs);
    }

    @Override
    protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
        if (Build.VERSION.SDK_INT >= 19 && p instanceof LinearLayout.LayoutParams) {
            return new LayoutParams((LinearLayout.LayoutParams)p);
        } else {
            return p instanceof MarginLayoutParams ? new LayoutParams((MarginLayoutParams)p) : new LayoutParams(p);
        }
    }

    // 作用于android:fitsSystemWindows标记开启后，状态栏的高度获取在需要的时候参与计算
    @VisibleForTesting
    final int getTopInset() {
        return this.lastInsets != null ? this.lastInsets.getSystemWindowInsetTop() : 0;
    }

    public void setCoordinatorHeaderListener(CoordinatorHeaderListener listener) {
        if(this.headerListeners == null) {
            this.headerListeners = new ArrayList<>();
        }
        if (listener != null && !this.headerListeners.contains(listener)) {
            this.headerListeners.add(listener);
        }
    }
    public void removeCoordinatorHeaderListener(CoordinatorHeaderListener listener) {
        if (this.headerListeners != null && listener != null) {
            this.headerListeners.remove(listener);
        }
    }

    public void setCoordinatorLayoutListener(CoordinatorLayoutListener listener) {
        if(this.layoutListeners == null) {
            this.layoutListeners = new ArrayList<>();
        }
        if (listener != null && !this.layoutListeners.contains(listener)) {
            this.layoutListeners.add(listener);
        }
    }
    public void removeCoordinatorLayoutListener(CoordinatorLayoutListener listener) {
        if (this.layoutListeners != null && listener != null) {
            this.layoutListeners.remove(listener);
        }
    }

    void dispatchCoordinatorHeaderMove(boolean isDragging, int offset) {
        if (this.headerListeners != null) {
            int i = 0;
            for(int z = this.headerListeners.size(); i < z; ++i) {
                CoordinatorHeaderListener listener = this.headerListeners.get(i);
                if (listener != null) {
                    listener.onHeaderMoveChanged(this, isDragging, offset);
                }
            }
        }

    }
    void dispatchCoordinatorLayoutMove(int offset) {
        if (this.layoutListeners != null) {
            int i = 0;

            for(int z = this.layoutListeners.size(); i < z; ++i) {
                CoordinatorLayoutListener listener = this.layoutListeners.get(i);
                if (listener != null) {
                    listener.onLayoutMoveChanged(this, offset);
                }
            }
        }

    }

    public static class CoordinatorBehavior extends ViewOffsetBehavior<View> implements CoordinatorHeaderListener, CoordinatorLayoutListener{

        private CoordinatorBarLayout barLayout;

        public CoordinatorBehavior() { }

        public CoordinatorBehavior(Context context, AttributeSet attrs) {
            super(context, attrs);
        }

        public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {
            boolean isDepends = dependency instanceof CoordinatorBarLayout;
            if(isDepends && ObjectUtil.isNull(barLayout)) {
                this.barLayout = (CoordinatorBarLayout) dependency;
            }
            return isDepends;
        }

        @Override
        protected void onBuildViewOffsetHelper(View child) {
            if(ObjectUtil.nonNull(barLayout)) {
                CoordinatorWrapper wrapper = ObjectUtil.as(child, CoordinatorWrapper.class);
                if(ObjectUtil.nonNull(wrapper)) {
                    wrapper.setCoordinatorHeaderListener(this::onHeaderMoveChanged);
                    wrapper.setCoordinatorLayoutListener(this::onLayoutMoveChanged);
                }
            }
        }

        @Override
        public boolean onDependentViewChanged(@NonNull CoordinatorLayout parent, @NonNull View child, @NonNull View dependency) {
            return false;
        }

        @Override
        public void onDependentViewRemoved(@NonNull CoordinatorLayout parent, @NonNull View child, @NonNull View dependency) {
            if(ObjectUtil.equals(barLayout, dependency)) {
                barLayout = null;
            }
        }

        @Override
        public void onHeaderMoveChanged(View child, boolean isDragging, int offSet) {
            if(ObjectUtil.nonNull(barLayout)) {
                barLayout.dispatchCoordinatorHeaderMove(isDragging, offSet);
            }
        }

        @Override
        public void onLayoutMoveChanged(View child, int offSet) {
            if(ObjectUtil.nonNull(barLayout)) {
                barLayout.dispatchCoordinatorLayoutMove(offSet);
            }
        }
    }

    public static class LayoutParams extends LinearLayout.LayoutParams {

        Interpolator scrollInterpolator;

        public LayoutParams(Context c, AttributeSet attrs) {
            super(c, attrs);
            TypedArray a = c.obtainStyledAttributes(attrs, R.styleable.CoordinatorBarLayout);
            if (a.hasValue(R.styleable.CoordinatorBarLayout_layout_scrollInterpolator)) {
                int resId = a.getResourceId(R.styleable.CoordinatorBarLayout_layout_scrollInterpolator, 0);
                this.scrollInterpolator = AnimationUtils.loadInterpolator(c, resId);
            }
            a.recycle();
        }

        public LayoutParams(int width, int height) {
            super(width, height);
        }

        public LayoutParams(int width, int height, float weight) {
            super(width, height, weight);
        }

        public LayoutParams(ViewGroup.LayoutParams p) {
            super(p);
        }

        public LayoutParams(MarginLayoutParams source) {
            super(source);
        }

        public LayoutParams(android.widget.LinearLayout.LayoutParams source) {
            super(source);
        }

        public LayoutParams(LayoutParams source) {
            super(source);
            this.scrollInterpolator = source.scrollInterpolator;
        }

        public void setScrollInterpolator(Interpolator interpolator) {
            this.scrollInterpolator = interpolator;
        }

        public Interpolator getScrollInterpolator() {
            return this.scrollInterpolator;
        }

    }

}
